#include "GameThread.h"
#include <windows.h>
#include "../Utils/LogUtil.h"
#include "../Utils/TimeUtil.h"
#include "../Core/CoreGlobals.h"
#include "../Thread/ThreadManager.h"
#include "GameState.h"
#include "../Input/Input.h"

GameState* GGameState;

GameThread::GameThread(std::shared_future<void>& startPromise, ThreadManager* threadManager) : TaskThread()
{
	mStartFuture = startPromise;
	mThreadManager = threadManager;
}

bool GameThread::Init()
{
	assert(TaskThread::Init());

	WaitForSingleObject(mThreadManager->mWaitRenderInit, INFINITE);
	CloseHandle(mThreadManager->mWaitRenderInit);
	mThreadManager->mWaitRenderInit = nullptr;

	// Must later renderState init
	LOGI(L"Game Init Pre");

	// the GameState will be init after RenderState init to get the frame count
	GGameState = new GameState();
	GGameState->Init();

	SetEvent(mThreadManager->mWaitGameInit);

	// Must before renderThread run
	LOGI(L"Game Init Post");
	
	return true;
}

uint32 GameThread::Run()
{
	// lock until main thread run
	mStartFuture.get();

	while (true)
	{
		Input::Get().Update();

		GGameState->WaitForRender();

		if (mThreadManager->IsTimeToExit())
		{
			break;
		}

		GGameState->MainLoop();

		ProcessTasksUntilReturn();

		GGameState->NextFrame();
	}

	GGameState->Stop();

	LOGI(L"Game Stop");

	WaitForSingleObject(mThreadManager->mWaitRenderExit, INFINITE);
	CloseHandle(mThreadManager->mWaitRenderExit);
	mThreadManager->mWaitRenderExit = nullptr;

	GGameState->Exit();

	SetEvent(mThreadManager->mWaitGameExit);

	LOGI(L"Game Exit");

	return 0;
}

void GameThread::Stop()
{
	TaskThread::Stop();

	delete GGameState;
	GGameState = nullptr;
}

void GameThread::Exit()
{
	TaskThread::Exit();
}
